package com.iphanta.community.user.service.impl;

import com.baidu.fsg.uid.UidGenerator;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iphanta.community.common.BusinessException;
import com.iphanta.community.common.UserUtils;
import com.iphanta.community.common.utils.JsonUtils;
import com.iphanta.community.common.utils.RedisKeyUtils;
import com.iphanta.community.common.utils.ResultUtils;
import com.iphanta.community.following.service.DynamicService;
import com.iphanta.community.following.traffic.vo.UserSimpleInfo;
import com.iphanta.community.mq.message.Notification;
import com.iphanta.community.remote.service.TimService;
import com.iphanta.community.user.entity.Relation;
import com.iphanta.community.user.entity.UserNotification;
import com.iphanta.community.user.mapper.RelationMapper;
import com.iphanta.community.user.entity.UserBasicInfo;
import com.iphanta.community.user.mapper.UserBasicInfoMapper;
import com.iphanta.community.user.mapper.UserNotificationMapper;
import com.iphanta.community.user.service.UserService;
import com.iphanta.community.user.traffic.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户相关接口
 *
 * @author 墨声 E-mail: zehong.hongframe.huang@gmail.com
 * create time: 2/22/22 11:35 AM
 */
@Service
public class UserServiceImpl implements UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);


    @Autowired
    private UserBasicInfoMapper userBasicInfoMapper;

    @Autowired
    private RelationMapper relationMapper;

    @Autowired
    private UidGenerator uidGenerator;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private TimService timService;

    /**
     * 用户注册
     *
     * @param request
     * @return
     */
    @Override
    public UserRegisterResponse register(UserRegisterRequest request) {
        UserRegisterResponse response = new UserRegisterResponse();

        UserBasicInfo basicInfo = this.userBasicInfoMapper.selectByUid(request.getUid());
        if (Objects.nonNull(basicInfo)) {
            response.setBrandNew(false);
            return response;
        }
        UserBasicInfo brandnew = new UserBasicInfo();
        brandnew.setId(this.uidGenerator.getUID());
        brandnew.setUid(request.getUid());
        brandnew.setNickname(request.getNickname());
        this.userBasicInfoMapper.insert(brandnew);

        Relation relation = new Relation();
        relation.setId(this.uidGenerator.getUID());
        relation.setFollowerId(request.getUid());
        relation.setFollowingId(request.getUid());
        relation.setIsDel(0);
        relation.setCreateTime(new Date());
        relation.setUpdateTime(new Date());
        this.relationMapper.insert(relation);

        this.timService.createUser(request.getUid(), request.getNickname(), request.getPhoto());

        response.setBrandNew(true);
        return response;
    }

    @Override
    public UserModifyResponse modify(UserModifyRequest request) {
        UserModifyResponse response = new UserModifyResponse();
        UserBasicInfo basicInfo = this.userBasicInfoMapper.selectByUid(UserUtils.getUid());
        if (Objects.isNull(basicInfo)) {
            throw new BusinessException("用户不存在", ResultUtils.FAIL_ON_BUSINESS.result());
        }
        if (Objects.nonNull(request.getNickname())) {
            basicInfo.setNickname(request.getNickname());
        }
        if (Objects.nonNull(request.getBio())) {
            basicInfo.setBio(request.getBio());
        }
        if (Objects.nonNull(request.getPhoto())) {
            basicInfo.setPhoto(request.getPhoto());
        }
        if (!CollectionUtils.isEmpty(request.getTags())) {
            String tags = String.join("|", request.getTags().stream().map(e -> e.getCode()).collect(Collectors.toList()));
            basicInfo.setTagCodes(tags);
        } else {
            basicInfo.setTagCodes("");
        }
        this.userBasicInfoMapper.updateUser(basicInfo);
        response.setModified(true);
        return response;
    }

    @Override
    public UserInfoResponse info(UserInfoRequest request) {
        UserInfoResponse response = new UserInfoResponse();
        String uid = null;
        Integer relation = null;
        if (!Objects.equals(request.getHostId(), UserUtils.getUid()) && StringUtils.isNotBlank(request.getHostId())) {
            uid = request.getHostId();
            relation = this.relationMapper.relation(UserUtils.getUid(), request.getHostId());
            if (Objects.isNull(relation)) {
                relation = 0;
            }
        } else {
            uid = UserUtils.getUid();
            String newlyFans = RedisKeyUtils.INSTANCE.key("newly_fans", UserUtils.getUid());
            String fans = this.redisTemplate.opsForValue().get(newlyFans);
            if (StringUtils.isNotBlank(fans)) {
                response.setNewlyFollower(Long.valueOf(fans));
            }
            this.redisTemplate.delete(newlyFans);
        }
        UserBasicInfo basicInfo = this.userBasicInfoMapper.selectByUid(uid);
        if (Objects.isNull(basicInfo)) {
            throw new BusinessException("用户不存在", ResultUtils.FAIL_ON_BUSINESS.result());
        }
        LOGGER.info("用户信息 >>>> {}", basicInfo);

        BeanUtils.copyProperties(basicInfo, response);
        response.setFollowing(this.relationMapper.followingCount(uid));
        response.setFollower(this.relationMapper.followerCount(uid));
        //TODO 点赞数
        response.setLikedCount(this.dynamicService.sumLikedCount(uid));
        response.setRelation(relation);
        return response;
    }

    @Autowired
    private UserNotificationMapper notificationMapper;

    @Autowired
    private DynamicService dynamicService;

    @Override
    public UserNotificationResponse notification(UserNotificationRequest request) {

        int size = 100;
        int start = size * (request.getPage() - 1);
        int end = start - 1 + size;

        String isReadKey = RedisKeyUtils.INSTANCE.key("notification", "is_read", request.getType(), UserUtils.getUid());
        this.redisTemplate.opsForValue().set(isReadKey, "1");

        String notificationKey = RedisKeyUtils.INSTANCE.key("notification", request.getType(), UserUtils.getUid());
        List<String> list = this.redisTemplate.opsForList().range(notificationKey, start, end);
        List<Notification> notifications = new ArrayList<>();
        for (String item : list) {
            Notification notification = JsonUtils.INSTANCE.toObject(item, Notification.class);

            notifications.add(notification);
        }
        int size_ = list.size();
        if (size_ < size) {
            int remain = size - size_;
            PageHelper.offsetPage(start + size_, remain);
            List<UserNotification> notifications_db = this.notificationMapper.selectByUid(UserUtils.getUid(), request.getType());
            PageInfo<UserNotification> pageInfo = new PageInfo<>(notifications_db);
            for (UserNotification item : pageInfo.getList()) {
                Notification notification = new Notification();
                BeanUtils.copyProperties(item, notification);
                notifications.add(notification);
            }
        }
        Map<Long, String> resJsons = null;
        if(Objects.equals(request.getType(), "like") || Objects.equals(request.getType(), "comment")) {
            List<Long> dynamicId = notifications.stream().map(item -> item.getMissId()).collect(Collectors.toList());
            resJsons = this.dynamicService.dynamicResJson(dynamicId);
        }

        for(Notification i : notifications) {
            UserSimpleInfo info = simpleInfo(i.getByUser());
            i.setByUserNickname(info.getNickname());
            i.setByUserPhoto(info.getPhoto());
            i.setByUserGameLevel(info.getGameLevel());
            if(!CollectionUtils.isEmpty(resJsons)) {
                i.setResJon(resJsons.get(i.getMissId()));
            }
        }
        UserNotificationResponse response = new UserNotificationResponse();
        response.setNotifications(notifications);
        return response;
    }

    @Override
    public UserNotificationReadResponse isRead() {
        String likeReadKey = RedisKeyUtils.INSTANCE.key("notification", "is_read", "like", UserUtils.getUid());
        String commentReadKey = RedisKeyUtils.INSTANCE.key("notification", "is_read", "comment", UserUtils.getUid());
        String followerReadKey = RedisKeyUtils.INSTANCE.key("notification", "is_read", "follower", UserUtils.getUid());
        String likeRead = this.redisTemplate.opsForValue().get(likeReadKey);
        likeRead = Objects.isNull(likeRead) ? "1" : likeRead;
        String commentRead = this.redisTemplate.opsForValue().get(commentReadKey);
        commentRead = Objects.isNull(commentRead) ? "1" : commentRead;
        String followerRead = this.redisTemplate.opsForValue().get(followerReadKey);
        followerRead = Objects.isNull(followerRead) ? "1" : followerRead;

        UserNotificationReadResponse readResponse = new UserNotificationReadResponse();
        readResponse.setLike(Objects.equals(likeRead, "1"));
        readResponse.setComment(Objects.equals(commentRead, "1"));
        readResponse.setFollower(Objects.equals(followerRead, "1"));
        readResponse.setHandPicked(true);
        return readResponse;
    }

    @Override
    public UserSimpleInfo simpleInfo(String uid) {
        String infoKey = RedisKeyUtils.INSTANCE.key("simple_user_info", uid);
        String infoMap = this.redisTemplate.opsForValue().get(infoKey);
        UserSimpleInfo simpleInfo = null;
        if (StringUtils.isBlank(infoMap)) {
            UserBasicInfo basicInfo = this.userBasicInfoMapper.selectByUid(uid);
            simpleInfo = new UserSimpleInfo();
            simpleInfo.setNickname(basicInfo.getNickname());
            simpleInfo.setPhoto(basicInfo.getPhoto());
            simpleInfo.setBio(basicInfo.getBio());
            simpleInfo.setGameLevel(basicInfo.getGameLevel());
            this.redisTemplate.opsForValue().set(infoKey, JsonUtils.INSTANCE.toJsonString(simpleInfo), 72, TimeUnit.HOURS);
            return simpleInfo;
        }
        simpleInfo = JsonUtils.INSTANCE.toObject(infoMap, UserSimpleInfo.class);
        return simpleInfo;
    }
}
